<?php
namespace Services;

use Models\Intersection;
use Models\GreenWaveSection;

/**
 * 绿波计算服务类
 */
class GreenWaveCalculator {
    private $intersection;
    private $section;
    
    public function __construct() {
        $this->intersection = new Intersection();
        $this->section = new GreenWaveSection();
    }
    
    /**
     * 计算绿波配时方案
     */
    public function calculateTimingPlan($sectionId, $params) {
        // 获取路段信息
        $section = $this->section->getSectionById($sectionId);
        if (!$section) {
            throw new \Exception("路段不存在");
        }
        
        // 获取路段所有路口
        $intersections = $this->section->getSectionIntersections($sectionId);
        if (empty($intersections)) {
            throw new \Exception("路段没有配置路口");
        }
        
        // 验证参数
        $this->validateParams($params);
        
        // 计算路口间距离
        $distances = $this->calculateDistances($intersections);
        
        // 计算绿波带
        $bandwidthResult = $this->calculateBandwidth(
            $intersections,
            $distances,
            $params['cycle_time'],
            $params['design_speed'],
            $params['direction']
        );
        
        // 生成配时方案
        $timingPlan = $this->generateTimingPlan(
            $intersections,
            $bandwidthResult,
            $params['cycle_time']
        );
        
        // 计算优化效率
        $efficiency = $this->calculateEfficiency($bandwidthResult, $params['cycle_time']);
        
        return [
            'timing_plan' => $timingPlan,
            'bandwidth' => $bandwidthResult['bandwidth'],
            'efficiency' => $efficiency,
            'offsets' => $bandwidthResult['offsets']
        ];
    }
    
    /**
     * 验证计算参数
     */
    private function validateParams($params) {
        $required = ['cycle_time', 'design_speed', 'direction'];
        foreach ($required as $field) {
            if (!isset($params[$field])) {
                throw new \Exception("缺少必要参数: {$field}");
            }
        }
        
        if ($params['cycle_time'] < 60 || $params['cycle_time'] > 180) {
            throw new \Exception("周期时长必须在60-180秒之间");
        }
        
        if ($params['design_speed'] < 20 || $params['design_speed'] > 60) {
            throw new \Exception("设计车速必须在20-60km/h之间");
        }
    }
    
    /**
     * 计算路口间距离
     */
    private function calculateDistances($intersections) {
        $distances = [];
        for ($i = 0; $i < count($intersections) - 1; $i++) {
            $distances[] = $this->calculateDistance(
                $intersections[$i]['latitude'],
                $intersections[$i]['longitude'],
                $intersections[$i + 1]['latitude'],
                $intersections[$i + 1]['longitude']
            );
        }
        return $distances;
    }
    
    /**
     * 计算两点间距离（米）
     */
    private function calculateDistance($lat1, $lng1, $lat2, $lng2) {
        $earthRadius = 6371000; // 地球半径（米）
        
        $lat1 = deg2rad($lat1);
        $lng1 = deg2rad($lng1);
        $lat2 = deg2rad($lat2);
        $lng2 = deg2rad($lng2);
        
        $dLat = $lat2 - $lat1;
        $dLng = $lng2 - $lng1;
        
        $a = sin($dLat/2) * sin($dLat/2) +
             cos($lat1) * cos($lat2) *
             sin($dLng/2) * sin($dLng/2);
             
        $c = 2 * atan2(sqrt($a), sqrt(1-$a));
        
        return $earthRadius * $c;
    }
    
    /**
     * 计算绿波带
     */
    private function calculateBandwidth($intersections, $distances, $cycleTime, $designSpeed, $direction) {
        // 转换设计车速为米/秒
        $speedMs = $designSpeed * 1000 / 3600;
        
        // 计算路口间行程时间
        $travelTimes = array_map(function($distance) use ($speedMs) {
            return $distance / $speedMs;
        }, $distances);
        
        // 初始化相位差数组
        $offsets = array_fill(0, count($intersections), 0);
        
        // 计算最大绿波带宽
        $maxBandwidth = 0;
        $bestOffsets = $offsets;
        
        // 遍历所有可能的相位差组合
        for ($i = 0; $i < $cycleTime; $i++) {
            $currentOffsets = $this->calculateOffsets($travelTimes, $i, $cycleTime);
            $bandwidth = $this->calculateCurrentBandwidth($currentOffsets, $cycleTime);
            
            if ($bandwidth > $maxBandwidth) {
                $maxBandwidth = $bandwidth;
                $bestOffsets = $currentOffsets;
            }
        }
        
        return [
            'bandwidth' => $maxBandwidth,
            'offsets' => $bestOffsets
        ];
    }
    
    /**
     * 计算相位差
     */
    private function calculateOffsets($travelTimes, $initialOffset, $cycleTime) {
        $offsets = [0];
        $currentOffset = $initialOffset;
        
        foreach ($travelTimes as $time) {
            $currentOffset = ($currentOffset + round($time)) % $cycleTime;
            $offsets[] = $currentOffset;
        }
        
        return $offsets;
    }
    
    /**
     * 计算当前相位差下的绿波带宽
     */
    private function calculateCurrentBandwidth($offsets, $cycleTime) {
        // 简化版计算，实际项目中需要考虑更多因素
        $minBandwidth = $cycleTime;
        
        for ($i = 0; $i < count($offsets) - 1; $i++) {
            $diff = abs($offsets[$i + 1] - $offsets[$i]);
            $bandwidth = min($diff, $cycleTime - $diff);
            $minBandwidth = min($minBandwidth, $bandwidth);
        }
        
        return $minBandwidth;
    }
    
    /**
     * 生成配时方案
     */
    private function generateTimingPlan($intersections, $bandwidthResult, $cycleTime) {
        $plan = [];
        
        foreach ($intersections as $i => $intersection) {
            $plan[] = [
                'intersection_id' => $intersection['id'],
                'intersection_name' => $intersection['name'],
                'cycle_time' => $cycleTime,
                'offset' => $bandwidthResult['offsets'][$i],
                'phases' => $this->generatePhases($cycleTime, $bandwidthResult['bandwidth'])
            ];
        }
        
        return $plan;
    }
    
    /**
     * 生成相位配时
     */
    private function generatePhases($cycleTime, $bandwidth) {
        // 简化版相位生成，实际项目中需要根据实际情况调整
        return [
            [
                'phase_number' => 1,
                'green_time' => $bandwidth,
                'yellow_time' => 3,
                'red_time' => $cycleTime - $bandwidth - 3
            ],
            [
                'phase_number' => 2,
                'green_time' => $cycleTime - $bandwidth - 6,
                'yellow_time' => 3,
                'red_time' => $bandwidth + 3
            ]
        ];
    }
    
    /**
     * 计算优化效率
     */
    private function calculateEfficiency($bandwidthResult, $cycleTime) {
        // 简化版效率计算，实际项目中需要考虑更多因素
        return round(($bandwidthResult['bandwidth'] / $cycleTime) * 100, 2);
    }
} 